﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Threading;
using System.Windows.Threading;
using IntoNails.Infrastructure;
using IntoNails.Infrastructure.EventAggregators;
using IntoNails.Infrastructure.Security;
using IntoNails.Infrastructure.InteractionRequests;
//using IntoNails.Infrastructure.Localizations;
using IntoNails.DataAccess;
using IntoNails.Models;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.ViewModel;
using IntoNails.Models;

namespace IntoNails.Modules.StartUp.ViewModels
{
    [Export(typeof (IStartUpViewModel))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class StartUpViewModel : NotificationObject, IStartUpViewModel
    {
        #region Fields

        private readonly IEventAggregator _eventAggregator;
        private readonly UserRepository _userRepository;

        private string _username;
        private string _password;
        private string _confirmedPassword;

        private UserType _selectedAuthority;
        private GenderType _selectedGender;
        private bool _isSignUpMode;
        private bool _showLoginPanel = true;

        private User _authorizedUser;

        #endregion

        #region Constructors

        [ImportingConstructor]
        public StartUpViewModel(IEventAggregator eventAggregator)
        {
            this._eventAggregator = eventAggregator;

            this._userRepository = new UserRepository(GlobalInfoCaches.StartUpPath + @"\User.dat");

            if (this._userRepository.Load() == 0)
            {
                this.IsSignUpMode = true;
                this.AuthorizedUser = User.CreateAdmin();
            }
            else
            {
                this.IsSignUpMode = false;

#if DEBUG
                // HACK: login
                this.Username = "admin";
                this.Password = "12345";
#endif
            }
            
            this.SelectLanguageCommand = new DelegateCommand<object>(this.OnLanguageSelected);
            this.OkCommand = new DelegateCommand(this.OnOkCommandExecuted);
            this.ExitCommand = new DelegateCommand(this.OnExitCommandExecuted);

            this.ShowMessageBox = new GenericInteractionRequest<MessageBoxContext>();
        }

        #endregion

        #region Implementation of IHeaderInfoProvider<string>

        public string HeaderInfo
        {
            get { return "Start Up"; }
        }

        #endregion

        #region Interaction Requests

        public GenericInteractionRequest<MessageBoxContext> ShowMessageBox { get; private set; }

        #endregion

        #region Properties

        public string Username
        {
            get { return this._username; }
            set
            {
                this._username = value;
                base.RaisePropertyChanged(() => Username);
            }
        }

        public string Password
        {
            get { return this._password; }
            set
            {
                this._password = value;
                base.RaisePropertyChanged(() => Password);
            }
        }

        public string ConfirmedPassword
        {
            get { return this._confirmedPassword; }
            set
            {
                this._confirmedPassword = value;
                base.RaisePropertyChanged(() => ConfirmedPassword);
            }
        }

        public User AuthorizedUser
        {
            get { return this._authorizedUser; }
            set
            {
                this._authorizedUser = value;
                base.RaisePropertyChanged(() => AuthorizedUser);
            }
        }

        public IEnumerable<UserType> AuthorityValues
        {
            get
            {
                return Enum.GetValues(typeof(UserType)).Cast<UserType>();
            }
        }

        public IEnumerable<GenderType> GenderValues
        {
            get
            {
                return Enum.GetValues(typeof(GenderType)).Cast<GenderType>();
            }
        }

        public UserType SelectedAuthority
        {
            get { return this._selectedAuthority; }
            set
            {
                this._selectedAuthority = value;
                base.RaisePropertyChanged(() => SelectedAuthority);
            }
        }

        public GenderType SelectedGender
        {
            get { return this._selectedGender; }
            set
            {
                this._selectedGender = value;
                base.RaisePropertyChanged(() => SelectedGender);
            }
        }

        public bool IsSignUpMode
        {
            get { return this._isSignUpMode; }
            set
            {
                this._isSignUpMode = value;
                base.RaisePropertyChanged(() => IsSignUpMode);
            }
        }

        public bool ShowLoginPanel
        {
            get { return this._showLoginPanel; }
            set
            {
                this._showLoginPanel = value;
                base.RaisePropertyChanged(() => ShowLoginPanel);
            }
        }

        #endregion

        #region Commands

        public ICommand SelectLanguageCommand { get; private set; }
        public ICommand ExitCommand { get; set; }
        public ICommand OkCommand { get; set; }

        #endregion

        private void OnLanguageSelected(object commandParam)
        {
            ////CultureInfo culture = CultureInfo.GetCultureInfo(commandParam as string);

            ////Dispatcher.CurrentDispatcher.Thread.CurrentCulture = culture;
            ////Dispatcher.CurrentDispatcher.Thread.CurrentUICulture = culture;

            ////LocalizationManager.UpdateValues();
        }

        private void OnOkCommandExecuted()
        {
            if (IsSignUpMode)
            {
                if (string.Compare(this.Password, this.ConfirmedPassword, StringComparison.InvariantCulture) == 0)
                {
                    this.AuthorizedUser.Username = this.Username;
                    this.AuthorizedUser.Password = this.Password.ComputeHash();
                    this.AuthorizedUser.Gender = this.SelectedGender;
                    this.AuthorizedUser.Authority = this.SelectedAuthority;

                    this._userRepository.Add(this.AuthorizedUser);
                    this._userRepository.Save();
                }
            }
            else
            {
                this.AuthorizedUser = this._userRepository.Login(this.Username, this.Password.ComputeHash());
            }

            if (this.AuthorizedUser != null)
            {
                // cache the user account
                GlobalInfoCaches.AuthorizedUser = this.AuthorizedUser;

                // TODO: write audit-trail

                // Hides the login panel.
                this.ShowLoginPanel = false;

                // Raises event to show the ribbon-bar.
                this._eventAggregator.GetEvent<ShowRibbonBarEventAggregators>().Publish(true);
            }
            else
            {
                this.ShowLoginPanel = false;

                MessageBoxContext context = new MessageBoxContext("Invalid username or password", "IntoNails 2012", MessageBoxButtons.OK, MessageBoxIcons.Error);
                this.ShowMessageBox.Raise(context,
                                          boxContext =>
                                              {
                                                  this.Password = string.Empty;
                                                  this.ShowLoginPanel = true;
                                              },
                                          () => { });
            }
        }

        private void OnExitCommandExecuted()
        {
            this.ShowLoginPanel = false;

            MessageBoxContext context = new MessageBoxContext("Exit IntoNails?", "IntoNails 2012", MessageBoxButtons.YesNo, MessageBoxIcons.Question);
            this.ShowMessageBox.Raise(context,
                                      boxContext => this._eventAggregator.GetEvent<SystemShutdownEventAggregator>().Publish(null),
                                      () => this.ShowLoginPanel = true);
        }
    }
}
